#ifndef CODE_LINES_H
#define CODE_LINES_H

#include <map>

#include "CodeLine.h"
#include "GOAL.h"

namespace GOAL
{

  /**
   * @class Status
   * @brief a generic status class
   * @see   Code_Lines, Code_Line
   */

  namespace Status
    {
      typedef unsigned int type;

      static const type UNCHECKED = 0;
      static const type ADDED = 1;
      static const type CHECKED = 2;
      static const type FINISHED = 0-1;
    }

  /**
   * @class Code_Lines
   * @brief a container of code lines
   * @see   Code_Line, Code_Line_Iterator
   */

  class Code_Lines
  {
  public:
    /// constructor
    Code_Lines (const Udm::Object & parent);

    /// destructor
    ~Code_Lines ();

    /// insert a GOAL::MgaObject into the code lines
    void insert (const MgaObject& object);
    
    /// retrieve the specified code line
    Code_Line & operator[] (unsigned int index);

    /// retrieve the specified code line
    const Code_Line & operator[] (unsigned int index) const;

    /// retrieve the specified code line
    Code_Line & operator[] (const MgaObject &object);

    /// retrieve the size
    unsigned int size ();

    /// checks if an object exists in this code line set
    bool exists (const MgaObject& object);

    /// returns the code line that the specified object is on
    unsigned int find (const GOAL::MgaObject& object);

    /// prune the code lines (maintenance). always do this after you
    /// are done inserting. It reduces the number of allocated code lines
    /// we could do this as we go, but it would be inefficient.
    void prune (void);

    /// get a sorted version of the code lines. WARNING: the returned code_lines
    /// will not function correctly with find(). It will retain the mappings of
    /// the non-sorted version
    Code_Lines getSorted (void);

    Code_Line & getLineByObject (const MgaObject& object);
  private:
    /// reroutes the lookup tables. Makes all indices to source point to
    /// dest instead. Does not copy the Code_Lines.
    void reroute (unsigned int source, unsigned int dest);

    /// Copies a source code_line to the end of a dest. 
    /// Also clears the source.
    void merge (Code_Line& source, Code_Line& dest);

    /// list maintained for find() and exists()
    std::map<MgaObject, 
      std::map<std::string, GOAL::Status::type> > object_lookups_;

    /// list of code lines
    std::vector<Code_Line> code_lines_;

    /// parent of all of these code lines. Not a reference since
    /// I can't be sure about whether or not the parent MgaObject
    /// will have scope throughout lifetime of code line.
    Udm::Object parent_;
  };

}
#endif
